/**
 * Copyright(c) 2014 Xunton Solutions
 *
 * History:
 *   15-1-19 上午12:06 Created by dwzhang
 */
package com.jade.modules.cms.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;
import com.jade.framework.base.util.Parameters;
import com.jade.modules.cms.CmsException;
import com.jade.modules.cms.Content;
import com.jade.modules.cms.ContentDao;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 采用JPA方式实现的内容数据接口。
 *
 * @author <a href="mailto:dwzhang@xunton.com">dwzhang</a> 
 * @version 1.0 15-1-19 上午12:06
 */
//@Named ("module_cmsContentDao")
public class JpaContentDao implements ContentDao
{
    @PersistenceContext (unitName = "default")
    protected EntityManager entityManager;

    @Caching (evict = {@CacheEvict (value = "module.cms.content.g", key = "#content.id"),
            @CacheEvict (value = "module.cms.content.l", allEntries = true),
            @CacheEvict (value = "module.cms.content.q", allEntries = true)})
    public void add(Content content)
            throws CmsException
    {
        entityManager.persist(content);
    }

    @Caching (evict = {@CacheEvict (value = "module.cms.content.g", key = "#content.id"),
            @CacheEvict (value = "module.cms.content.l", allEntries = true),
            @CacheEvict (value = "module.cms.content.q", allEntries = true)})
    public void update(Content content)
            throws CmsException
    {
        entityManager.merge(content);
    }

    @Caching (evict = {@CacheEvict (value = "module.cms.content.g", key = "#id"),
            @CacheEvict (value = "module.cms.content.l", allEntries = true),
            @CacheEvict (value = "module.cms.content.q", allEntries = true)})
    public int update(long id, Parameters params, int[] statuses)
            throws CmsException
    {
        params.remove("id");
        if (params.isEmpty()) {
            throw new IllegalArgumentException("There is one field at least to update");
        }

        StringBuilder hsql = new StringBuilder();
        hsql.append("UPDATE com.jade.modules.cms.Content SET ");
        Iterator<String> names = params.getNames();
        while (names.hasNext()) {
            String name = names.next();
            hsql.append(name).append("=:").append(name);
            if (names.hasNext()) {
                hsql.append(", ");
            }
            else {
                hsql.append(" ");
            }
        }
        hsql.append("WHERE id=:id ");
        if (statuses != null && statuses.length > 0) {
            hsql.append("AND status in :oldStatus");
        }

        Query query = this.entityManager.createQuery(hsql.toString());
        names = params.getNames();
        while (names.hasNext()) {
            String name = names.next();
            query.setParameter(name, params.getObject(name));
        }
        if (statuses != null && statuses.length > 0) {
            List<Integer> list = new ArrayList<Integer>();
            for (int status : statuses) {
                list.add(status);
            }
            query.setParameter("oldStatus", list);
        }
        query.setParameter("id",id);
        return query.executeUpdate();
    }

    @Caching (evict = {@CacheEvict (value = "module.cms.content.g", key = "#content.id"),
            @CacheEvict (value = "module.cms.content.l", allEntries = true),
            @CacheEvict (value = "module.cms.content.q", allEntries = true)})
    public void remove(Content content)
            throws CmsException
    {
        Content old = entityManager.find(Content.class, content.getId());
        if (old != null) {
            entityManager.remove(old);
        }
    }

    @Cacheable (value = "module.cms.content.g", key = "#id")
    public Content get(long id)
    {
        return entityManager.find(Content.class, id);
    }

    @Cacheable (value = "module.cms.content.l", key = "#criteria")
    public List<Content> list(Criteria criteria)
    {
        return SqlUtils.sqlQueryWithoutCount(SQL_SOFT, entityManager, criteria);
    }

    @Cacheable (value = "module.cms.content.q", key = "#criteria")
    public PagingList<Content> query(Criteria criteria)
    {
        return SqlUtils.sqlQuery(SQL_SOFT, entityManager, criteria);
    }

    protected static final String SQL_SOFT = "SELECT content FROM com.jade.modules.cms.Content content";
}
